package com.fpt.mockproject.j21.absd.util;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Projections;

import com.fpt.mockproject.j21.absd.dao.HibernateSimplizer;

/**
 * HSP : Hibernate-Simplizer-Paginator
 * library required : HibernateSimplizer version 1.2
 * Paginator library API. Use for auto paging using hibernate
 * @author Linh HB Breaker
 * @version 1.0
 */
public class HSP<E> {
	
	/**
	 * current page which page want to trace
	 */
	protected long currentPage = 1;
	
	/**
	 * the maximum amount of result on one page
	 */
	protected long maxResult   = 10;
	
	/**
	 * When you create new object and insert the Object class
	 * This system will auto detect the total record in the table in database
	 */
	protected long totalRecord = 0;
	
	/**
	 * When has total record + max result, the system will show you total of page
	 * (maximum page)
	 */
	protected long totalPage   = 0;
	
	/**
	 * The mapping class which use for auto mapping by hibernate to a table in database
	 */
	protected Class<?> annotatedClass = Object.class;
	
	/**
	 * Constructor
	 * @param pageNumberWantToGet : the page you want to show record on that page (1, 2, 3...?)
	 * @param annotatedClass : mapping class
	 * @param maxResult : the max amount of record on this page
	 */
	public HSP(long pageNumberWantToGet, Class<?> annotatedClass, long maxResult) {
		
		if(pageNumberWantToGet <= 0)
			this.currentPage = 1;
		else
			this.currentPage = pageNumberWantToGet;
		
		this.annotatedClass = annotatedClass;
		
		HibernateSimplizer hdb = new HibernateSimplizer<>();
		Session session = hdb.getSession();
		Transaction tx = session.beginTransaction();
		
		Criteria criteria = session.createCriteria(this.annotatedClass);
		criteria.setProjection(Projections.rowCount());
		List result = criteria.list();
		
		if (!result.isEmpty()) {
			this.totalRecord = (long) result.get(0);
        }
		
		if(maxResult <= 0)
			maxResult = 1;
		
		if(maxResult > this.totalRecord)
			this.maxResult = this.totalRecord;
		else
			this.maxResult = maxResult;
		
		this.totalPage = (long) Math.ceil((double)this.totalRecord/(double)this.maxResult);
		
		if(this.currentPage > this.totalPage)
			this.currentPage = this.totalPage;
		
		tx.commit();
		hdb.close();
	}
	
	/**
	 * When init done, call this method to start fetching records from database and deliver it to the List
	 * @return List<E> : E Mapping class, List<E> : is the list contain total max result
	 */
	public List<E> fetch() {
		long indexRow = this.currentPage*this.maxResult - this.maxResult;
		HibernateSimplizer<E, ?> hdb = new HibernateSimplizer<>(this.annotatedClass);
		List<E> list = hdb.getFromTo((int)indexRow, (int)this.maxResult);
		hdb.close();
		return list;
	}
	
	public long getCurrentPage() {
		return currentPage;
	}
	public void setCurrentPage(long currentPage) {
		this.currentPage = currentPage;
	}
	public long getMaxResult() {
		return maxResult;
	}
	public void setMaxResult(long maxResult) {
		this.maxResult = maxResult;
	}
	public long getTotalRecord() {
		return totalRecord;
	}
	public void setTotalRecord(long totalRecord) {
		this.totalRecord = totalRecord;
	}
	public long getTotalPage() {
		return totalPage;
	}
	public void setTotalPage(long totalPage) {
		this.totalPage = totalPage;
	}
}
